package main

import (
	"fmt"
	"log"
	"net"
	"runtime"
	"time"
)

func catchErr(err error) {
	if err != nil {
		log.Fatalln(err)
	}
}

func main() {
	laddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:9999")
	catchErr(err)
	fmt.Println(laddr)
	// 1socket 2 bind
	server, err := net.ListenUDP("udp", laddr)
	catchErr(err)
	defer server.Close()
	// 不需要 accept

	// 3 收发
	buffer := make([]byte, 1024)
	exit := make(chan struct{})

	go func() {
		for {
			server.SetReadDeadline(time.Now().Add(time.Second))
			n, raddr, err := server.ReadFromUDP(buffer)
			fmt.Printf("%T, %[1]v\n", err)
			if err != nil {
				if _, ok := err.(*net.OpError); !ok {
					exit <- struct{}{}
					return
				}
				continue
			}
			msg := fmt.Sprintf("client=%v, data=%s", raddr, string(buffer[:n]))
			fmt.Println(msg)
			server.WriteToUDP([]byte(msg), raddr)
		}
	}()

	t := time.NewTicker(3 * time.Second)
	for {
		select {
		case <-exit:
			goto EXIT
		case <-t.C:
			fmt.Println(runtime.NumGoroutine(), "@@@")
		}
	}

EXIT:
	fmt.Println("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")

}
